/*
 * Copyright (C) 2022 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQml 2.12
import QtGraphicalEffects 1.0
import org.ukui.tablet 1.0
import org.ukui.qqc2style.private 1.0 as StylePrivate
import "./baseComponent"
import "."

Item {
    id: appIconContainer
    property Item rootItem: undefined
    property int type: LauncherItem.AppIcon
    property string icon: ""
    property var groupModel: undefined
    property int itemId: -1
    property int containerState: LauncherItem.Normal
    property string groupName: ""
    property int deleteIconWidth: 40
    property int dropShadowOffset: 3
    property alias pageContainer: group
    property var mapGroup: iconRect
    property bool allowGroupItemToTaskbar: false
    property int widgetColumn
    property int widgetRow
    signal deleteIconSig()
    signal groupItemToDesktop(int itemId, int pageIndex)

    function groupHeight() {
        if (type === LauncherItem.Group) {
            if (modelManager.groupPageCount(itemId) > 1) {
                return (4 * 170 + 13 + 43) * Style.tabletScaleFactor
            }
            return (Math.ceil(modelManager.groupPageItemCount(itemId, 0) / 4) * 170 + 13 + 43) * Style.tabletScaleFactor
        }
        return -1
    }
    function scrollToLastPage() {
        group.pageContainer.currentIndex = group.pageContainer.count - 1
    }

    clip: false

    Rectangle {
        id: underBackground
        width: 112 * Style.tabletScaleFactor
        height: 112 * Style.tabletScaleFactor
        anchors.centerIn: parent
        visible: containerState === LauncherItem.Under
        color: Qt.rgba(0, 0, 0, 0.8)
        radius: 24 * Style.tabletScaleFactor
    }

    Rectangle {
        id: iconRect
        width: parent.width; height: parent.height
        color: "transparent"
        radius: 24 * Style.tabletScaleFactor
        z: 1
        property var parentItem: iconRect

        Rectangle {
            id: iconRectBackground
            width: iconRect.width
            height: iconRect.height
            radius: iconRect.radius
            anchors.fill: iconRect
            color: appIconContainer.type === LauncherItem.Group ? "#F7F7F7" : "transparent"
            opacity: appIconContainer.type === LauncherItem.Group ? 0.5 : 1
        }

        DropArea {
            id: dropArea
            anchors.fill: parent
            enabled: containerState === LauncherItem.Popup
            property bool setValue: false
            property int dragItemId: drag.source == null ? -100 : drag.source.itemId
            property int dragPageIndex: drag.source == null ? -100 : drag.source.pageIndex
            TabletLauncherItemView {
                id: group
                clip: true
                groupId: appIconContainer.itemId
                height: {
                    switch (containerState) {
                    case LauncherItem.Popup: return parent.height - 13 * 2 * Style.tabletScaleFactor;
                    default: return 18 * 4 * Style.tabletScaleFactor;
                    }
                }
                width: {
                    switch (containerState) {
                    case LauncherItem.Popup: return parent.width - 13 * 2 * Style.tabletScaleFactor;
                    default: return 18 * 4 * Style.tabletScaleFactor;
                    }
                }
                anchors.centerIn: parent
                visible: type === LauncherItem.Group
                viewMoel: groupModel

                cellWidth: {
                    switch (containerState) {
                    case LauncherItem.Popup: return group.width / 4
                    default: return 18 * Style.tabletScaleFactor;
                    }
                }
                cellHeight: cellWidth
                iconSize: {
                    switch (containerState) {
                    case LauncherItem.Popup: return 96 * Style.tabletScaleFactor;
                    default: return 16 * Style.tabletScaleFactor;
                    }
                }
                allowGroupItemToTaskbar: appIconContainer.allowGroupItemToTaskbar
                Component.onCompleted: {
                    group.launcherItemToDesktop.connect(function() {
                        groupItemToDesktop(dropArea.dragItemId, dropArea.dragPageIndex)
                    })
                }
            }

            PageSwitchIndicator {
                id: pageIndicator
                visible: group.listViewItemCount() > 1 &&
                         type === LauncherItem.Group &&
                         containerState === LauncherItem.Popup
                anchors.bottom: parent.bottom
                anchors.bottomMargin: 16 * Style.tabletScaleFactor
                anchors.horizontalCenter: parent.horizontalCenter
                pageContainer: group.pageContainer
            }
        }
        Image {
            id: appIconImage
            anchors.fill: parent
            anchors.centerIn: parent
            visible: type === LauncherItem.AppIcon
            sourceSize: Qt.size(parent.width, parent.width)
            source: icon
            onStatusChanged: {
                if (status == Image.Error) {
                    reloadImageTimer.start();
                } else if (status == Image.Ready) {
                    reloadImageTimer.stop();
                }
            }
            Timer {
                id: reloadImageTimer
                property int reloadCounter: 0
                repeat: true
                interval: 1000
                onTriggered: {
                    appIconImage.source = ""
                    appIconImage.source = Qt.binding(function () { return icon })
                    ++ reloadCounter
                    if (reloadCounter > 30) {
                        reloadImageTimer.stop()
                        reloadCounter = 0
                        console.warn("Can not load the app icon:", icon)
                    }
                }
            }
        }
        DropShadow {
            anchors.fill: appIconImage
            horizontalOffset: dropShadowOffset
            radius: dropShadowOffset
            samples: dropShadowOffset * 2 + 1
            color: "#000000"
            opacity: 0.15
            source: appIconImage
        }

        Loader {
            id: widgetLoader
            width: Style.appIconGridWidth * widgetColumn
            height: Style.appIconGridHeight * widgetRow
            anchors.centerIn: parent
            source: visible ? "file://"+ modelData.qmlFile : ""
            visible: type === LauncherItem.Widget
            asynchronous: true

            function updateWidgetStatus() {
                if (containerState == LauncherItem.Editable) {
                    widgetLoader.item.userstatus = "Editable"
                } else if (containerState == LauncherItem.Normal) {
                    widgetLoader.item.userstatus = "Normal"
                }
            }

            function registerWidget() {
                widgetLoader.updateWidgetStatus()
                widgetLoader.item.register(widgetLoader.item.appname, "tablet-desktop")
            }

            onLoaded: {
                if (WidgetProperty.appWidgetExists(item.appname)) {
                    widgetLoader.registerWidget()
                } else {
                    widgetLoaderTimer.start()
                    WidgetProperty.appWidgetList.push(item.appname)
                }
            }
            onStatusChanged: {
                if (status == Loader.Null) {
                    warningText.text = qsTr("Widget is Null")
                }
                if (status == Loader.Error) {
                    warningText.text = qsTr("Loading widget Error")
                }
            }

            Timer {
                id: widgetLoaderTimer
                interval: 5000
                onTriggered: {
                    widgetLoader.registerWidget()
                }
            }

            Text {
                id: warningText
                anchors.centerIn: parent
                font { pointSize: 18; weight: Font.Medium
                       styleName: StylePrivate.StyleHelper.font.styleName
                       family: StylePrivate.StyleHelper.font.family }
                visible: type === LauncherItem.Widget &&
                         (widgetLoader.status == Loader.Null
                          || widgetLoader.status == Loader.Error)
            }
        }

        Image {
            id: deleteIcon;
            visible: containerState === LauncherItem.Editable &&
                     type === LauncherItem.AppIcon && modelData.uninstallable
            anchors {
                right: iconRect.right; rightMargin: -(deleteIconWidth/4) * Style.tabletScaleFactor
                top: iconRect.top; topMargin: -(deleteIconWidth/4) * Style.tabletScaleFactor
            }
            source: "qrc:/ui/images/desktop-uninstallbtn.png"
            width: deleteIconWidth * Style.tabletScaleFactor
            height: deleteIconWidth * Style.tabletScaleFactor
            antialiasing: true
            MouseArea {
                id: deleteMouseArea
                anchors.fill: parent
                onClicked: deleteIconSig()
            }
        }

        GroupTitleEdit {
            id: titleEdit
            title: groupName
            width: parent.width
            height: 92 * Style.tabletScaleFactor
            anchors.bottom: parent.top
            anchors.bottomMargin: 19 * Style.tabletScaleFactor
            visible: false
            onInputTitleChanged: {
                modelManager.setGroupName(newTitle, itemId)
            }
        }

        states: [
            State {
                name: "Popup"; when: containerState === LauncherItem.Popup
                ParentChange {
                    target: iconRect; parent: groupPopupLayer;
                    x: (rootItem.width - 706 * Style.tabletScaleFactor) / 2;
                    y: (rootItem.height - groupHeight()) / 2;
                    width: 706 * Style.tabletScaleFactor
                    height: groupHeight()
                }
                PropertyChanges { target: iconRectBackground; color: "#FAFAFA"; opacity: 0.45; }
                PropertyChanges { target: groupPopupBackground; visible: true; }
                PropertyChanges { target: titleEdit; visible: true; }
                StateChangeScript { script: {
                        delegateContent.z = 100
                        containerAnimation.stop()
                        iconRect.rotation = 0
                        group.placeholderAdded.connect(function() {
                            iconRect.height = Qt.binding(appIconContainer.groupHeight)
                        })
                        titleEdit.state = "Normal"
                    }
                }
            },
            State {
                name: "Under"; when: containerState === LauncherItem.Under
                StateChangeScript { script: { containerAnimation.stop(); iconRect.rotation = 0 } }
                PropertyChanges {
                    target: appIconContainer
                    opacity: 0.5
                }
            },
            State {
                name: "Editable"; when: containerState === LauncherItem.Editable
                StateChangeScript { script: { containerAnimation.start(); iconRect.scale = 1; } }
            },
            State {
                name: "Normal"; when: containerState === LauncherItem.Normal
                StateChangeScript {
                    script: {
                        group.update()
                        group.pageContainer.currentIndex = 0
                        containerAnimation.stop()
                        iconRect.rotation = 0
                        iconRect.scale = 1
                        titleEdit.state = "Hide"
                    }
                }
            },
            State {
                name: "HeightChange"
                ParentChange {
                    target: iconRect; parent: groupPopupLayer;
                    x: (rootItem.width - 706 * Style.tabletScaleFactor) / 2;
                    y: (rootItem.height - groupHeight()) / 2;
                    width: 706 * Style.tabletScaleFactor
                    height: groupHeight()
                }
                PropertyChanges { target: iconRectBackground; color: "#FAFAFA"; opacity: 0.45; }
                PropertyChanges { target: groupPopupBackground; visible: true; }
                PropertyChanges { target: titleEdit; visible: true; }
                StateChangeScript { script: {
                        delegateContent.z = 100
                        containerAnimation.stop()
                        iconRect.rotation = 0
                        group.placeholderAdded.connect(function() {
                            iconRect.height = Qt.binding(appIconContainer.groupHeight)
                        })
                    }
                }
            }
        ]

        transitions: Transition {
            ParentAnimation {
                NumberAnimation { properties: "x,y,width,height"; duration: 200;} }
            onRunningChanged: {
                if (containerState === LauncherItem.Normal) {
                    group.pageContainer.currentIndex = 0
                }
                group.groupAnimationState = running
            }
        }
        Component.onCompleted: {
            group.focusStateChanged.connect(function() {
                titleEdit.state = "Normal"
            })
            group.changeGroupHeight.connect(function() {
                if (state == "Popup") {
                    state = "HeightChange"
                } else if (state == "HeightChange") {
                    state = "Popup"
                }
            })
        }
    }

    SequentialAnimation {
        id: containerAnimation;
        loops: AnimatedSprite.Infinite;
        ParallelAnimation {
            RotationAnimation { target: iconRect; from: 0; to: 2; duration: 150; easing.type: Easing.OutCubic; }
        }
        ParallelAnimation {
            RotationAnimation { target: iconRect; from: 2; to: -2; duration: 150; easing.type: Easing.OutCubic; }
        }
    }

    Component.onCompleted: {
    }
}
